今天,我們會來介紹在實作註冊功能的新手注意事項~
會簡單解釋 Bad Practice & Good Practice 的差異性,Let's get started!
需求
我們會需要使用者輸入以下元素:
username、email、password、passwordConfirmed
以下暫時省略 Error Handling 的部分:
export.signup = async(req,res,next) => {
// 以下是不好的範例
const newUser = await User.create(req.body);
res.status(201).json({
status: 'success',
data: {
user: newUser
}
});
}
說明:
上述的方法常常會在新手教學中看到,而有時候使用這種直接 create req.body
的方式 ( 或是直接 post、update 整包 req.body
) 很有可能造成無意間幫 user 升級 role 到 admin 了! 因為也會跟著儲存其他欄位的 data 到 DB 內。
export signup = async(req, res, next) => {
const newUser = await User.create({
name: req.body.name,
email: req.body.email,
password: req.body.password,
passwordConfirmed: req.body.passwordConfirmed
});
res.status(201).json({
status: 'success',
data: {
user: newUser
}
});
}
說明:
明確指定要 create 那些 req.body.param (這邊的 param 請替換成 column 名稱),避免也跟著新增不必要的資訊。
在此處我們使用 jsonwebtoken , 在使用之前我們需要先下載他,在 command 中下:
npm i jsonwebtoken
exports.signup = async (req, res, next) => {
// 以下是第一步的 good practice
const newUser = await User.create({
name: req.body.name,
email: req.body.email,
password: req.body.password,
passwordConfirmed: req.body.passwordConfirmed
});
// 主要加入的地方: 以下為需要解說的不良示範
const token = jwt.sign({ id: newUser._id }, 'secret', { expiresIn: '90d'});
// 以下是第一步的 good practice
res.status(201).json({
status: 'success',
token,
data: {
user: newUser
}
});
}
解說:
此處不好的示範有兩點,仔細看一下以下節錄自上面的程式碼:
const token = jwt.sign({ id: newUser._id }, 'secret', { expiresIn: '90d'});
jwt
加密的 secret
,然而這真的太短了,也是網路上範例常見的,最好是使用你自己專屬的 32 個字符作為 secretsecret
或是 token exprireIn
,這邊直接寫在此處,沒有使用一個檔案來管理他 (ex. env),這麼做也會存在另外一個風險,就是當你直接 push 上 github,他就直接被洩漏了XDexports.signup = async (req, res, next) => {
// 以下是第一步的 good practice
const newUser = await User.create({
name: req.body.name,
email: req.body.email,
password: req.body.password,
passwordConfirmed: req.body.passwordConfirmed
});
// 主要加入的地方: 以下為需要解說的比較好的示範
const token = jwt.sign({ id: newUser._id }, process.env.JWT_SECRET, { expiresIn: process.new.JWT_EXPIREIN});
// 以下是第一步的 good practice
res.status(201).json({
status: 'success',
token,
data: {
user: newUser
}
});
}
解說:
比較好的方式就是把 secret 換成專屬於自己持有的 32 個字符,並且把需要管理的參數存在 .env
,最後,記得將 .env
放你的 .gitignore
檔案中。
終於開始進行 Node.js 的安全實踐啦! 真。建立漏洞 (?
雖然最近身體還是有點不適,但我想還是會越來越好的吧 ~
Udemy Node.js, Express, MongoDB & More: The Complete Bootcamp 2023:
https://www.udemy.com/course/nodejs-express-mongodb-bootcamp
Hacksplaining:
https://www.hacksplaining.com/